package com.caigou.util;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

public class RandomImageUtil {

    /**
     *
     * @param interLine 干扰线数量
     * @param textCode 验证码文字
     * @param randomLocation 每个字符高低是否随机
     */
    public static BufferedImage RandomImage(String textCode,int width,int height,int interLine, boolean randomLocation,Color backColor,Color lineColor,Color foreColor){

        // 创建BufferedImage对象
        // 如果把BufferedImage比作是画板，那么Graphics就是画纸，这样比较好理解，后续的操作都是在这画纸上进行的
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.createGraphics();
        // 随机操作对象
        Random random = new Random();
        // 绘制背景
        // Graphics有个setColor()方法，可以理解为画笔，在绘制任何东西前要选好画笔，然后调用fillRect进行轮廓的绘制，后续的绘制范围不会超过这个轮廓
        graphics.setColor(backColor == null?new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)): backColor);
        graphics.fillRect(0,0,width,height);
        // 绘制干扰线
        // 调用drawLine画直线，绘制不超过interLine条干扰线
        if (interLine > 0){
            int x = random.nextInt(4);
            int y = 0;
            int x1 = width - random.nextInt(4);
            int y1 = 0;
            for (int i=0; i<interLine; i++){
                graphics.setColor(lineColor == null?new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)): lineColor);
                y = random.nextInt(height - random.nextInt(4));
                y1 = random.nextInt(height - random.nextInt(4));
                graphics.drawLine(x,y,x1,y1);
            }
        }
        // 写验证码
        // 写验证码时调用drawString()方法，为了不整整齐齐而且重叠的写，应将每个字符的高度和水平位置随机，重点在于每绘制完一个字符后，
        // 需将画笔的水平坐标往右边移动一定的位置，这里我用了依据宽度浮动，可不必照搬这里的，有合适的算法就行
        int fSize = (int) (height * 0.8); //字体大小为图片高度的80%
        int fx = 0;
        int fy = fSize;
        graphics.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,fSize));
        // 写字符
        for (int i=0; i<textCode.length(); i++){
            fy = randomLocation?(int)((Math.random()*0.3+0.6)*height):fy;
            graphics.setColor(foreColor == null?new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)):foreColor);
            graphics.drawString(textCode.charAt(i)+"",fx,fy);
            fx+=(width / textCode.length()) * (Math.random() * 0.3 + 0.8); //依据宽度浮动
        }
//        // 扭曲图片
//        // 图片的扭曲就是将图片的水平和垂直按不同比例来平抑，copyArea()方法简单明了，直接是复制区域，也是同个意识
//        shearX(graphics,width,height,new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
//        shearY(graphics,width,height,new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
//        // 添加噪点
//        // 噪点的添加实质上就是在画纸上没有规律的点点点...，所以用随机颜色随机位置来执行image.setRGB()方法最合适了
//        float yawpRate = 0.05f;// 噪声率
//        int area = (int) (yawpRate * width * height);//噪点数量
//        for (int i=0; i<area; i++){
//            int xxx = random.nextInt(width);
//            int yyy = random.nextInt(height);
//            int rgb = new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)).getRGB();
//            image.setRGB(xxx, yyy, rgb);
//        }
//        // 封笔
//        // 以上一切画完之后，下一步就是封笔了，思来想去这样表达最合适，绘制完之后就是放好笔，收起画纸，这里就是返回BufferedImage对象
        graphics.dispose();
        return image;
    }

    private static void shearX(Graphics graphics, int width, int height, Color color){
        Random random = new Random();
        int period = 2;
        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i=0; i<height; i++){
            double d = (double) (period >> 1)* Math.sin((double) i / (double) period + (2.2831853071795862D * (double) phase)/ (double) frames);
            graphics.copyArea(0,i,width,1,(int) d,0);
            if (borderGap){
                graphics.setColor(color);
                graphics.drawLine((int) d, i, 0, i);
                graphics.drawLine((int) d + width, i, width, i);
            }
        }
    }

    private static void shearY(Graphics graphics, int width, int height, Color color){
        Random random = new Random();
        int period = random.nextInt(40) + 10; // 50;
        boolean borderGap = true;
        int frames = 20;
        int phase = random.nextInt(2);

        for (int i=0; i<width; i++){
            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (2.2831853071795862D * (double) phase)/ (double) frames);
            graphics.copyArea(i, 0, 1, height, 0, (int) d);
            if (borderGap){
                graphics.setColor(color);
                graphics.drawLine(i, (int) d, i, 0);
                graphics.drawLine(i, (int) d + height, i, height);
            }
        }
    }
}
